package br.com.pyramides.utils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 *
 * @author TechGeo
 */
public class DataHoraUtil {

    /** 
     * Calcula a diferença de duas datas em dias 
     * <br> 
     * <b>Importante:</b> Quando realiza a diferença em dias entre duas datas, este método considera as horas restantes e as converte em fração de dias. 
     * @param dataInicial 
     * @param dataFinal 
     * @return quantidade de dias existentes entre a dataInicial e dataFinal. 
     */
    public static double diferencaEmDias(Date dataInicial, Date dataFinal) {
        double result = 0;
        long diferenca = dataFinal.getTime() - dataInicial.getTime();
        double diferencaEmDias = (diferenca / 1000) / 60 / 60 / 24; //resultado é diferença entre as datas em dias  
        long horasRestantes = (diferenca / 1000) / 60 / 60 % 24; //calcula as horas restantes  
        result = diferencaEmDias + (horasRestantes / 24d); //transforma as horas restantes em fração de dias  

        return result;
    }

    /** 
     * Calcula a diferença de duas datas em horas 
     * <br> 
     * <b>Importante:</b> Quando realiza a diferença em horas entre duas datas, este método considera os minutos restantes e os converte em fração de horas. 
     * @param dataInicial 
     * @param dataFinal 
     * @return quantidade de horas existentes entre a dataInicial e dataFinal. 
     */
    public static double diferencaEmHoras(Date dataInicial, Date dataFinal) {
        double result = 0;
        long diferenca = dataFinal.getTime() - dataInicial.getTime();
        long diferencaEmHoras = (diferenca / 1000) / 60 / 60;
        long minutosRestantes = (diferenca / 1000) / 60 % 60;
        double horasRestantes = minutosRestantes / 60d;
        result = diferencaEmHoras + (horasRestantes);

        return result;
    }

    /** 
     * Calcula a diferença de duas datas em minutos 
     * <br> 
     * <b>Importante:</b> Quando realiza a diferença em minutos entre duas datas, este método considera os segundos restantes e os converte em fração de minutos. 
     * @param dataInicial 
     * @param dataFinal 
     * @return quantidade de minutos existentes entre a dataInicial e dataFinal. 
     */
    public static double diferencaEmMinutos(Date dataInicial, Date dataFinal) {
        //        double result = 0;
        long diferenca = dataFinal.getTime() - dataInicial.getTime();
        double diferencaEmMinutos = (diferenca / 1000) / 60; //resultado é diferença entre as datas em minutos  
        //        long segundosRestantes = (diferenca / 1000) % 60; //calcula os segundos restantes  
        //        result = diferencaEmMinutos + (segundosRestantes / 60d); //transforma os segundos restantes em minutos  

        return diferencaEmMinutos;
    }

    /**  
     * Retorna o valor do horário minimo para a data de referencia passada.  
     * <BR>  
     * <BR> Por exemplo se a data for "30/01/2009 as 17h:33m:12s e 299ms" a data  
     * retornada por este metodo será "30/01/2009 as 00h:00m:00s e 000ms".  
     * @param date de referencia.  
     * @return {@link Date} que representa o horário minimo para dia informado.  
     */
    public static Date lowDateTime(Date date) {
        Calendar aux = Calendar.getInstance();
        aux.setTime(date);
        toOnlyDate(aux); //zera os parametros de hour,min,sec,milisec    
        return aux.getTime();
    }

    /**  
     * Retorna o valor do horário maximo para a data de referencia passada.  
     * <BR>  
     * <BR> Por exemplo se a data for "30/01/2009 as 17h:33m:12s e 299ms" a data  
     * retornada por este metodo será "30/01/2009 as 23h:59m:59s e 999ms".  
     * @param date de referencia.  
     * @return {@link Date} que representa o horário maximo para dia informado.  
     */
    public static Date highDateTime(Date date) {
        Calendar aux = Calendar.getInstance();
        aux.setTime(date);
        toOnlyDate(aux); //zera os parametros de hour,min,sec,milisec    
        aux.roll(Calendar.DATE, true); //vai para o dia seguinte    
        aux.roll(Calendar.MILLISECOND, false); //reduz 1 milisegundo    
        return aux.getTime();
    }

    /**  
     * Zera todas as referencias de hora, minuto, segundo e milesegundo do  
     * {@link Calendar}.  
     * @param date a ser modificado.  
     */
    public static void toOnlyDate(Calendar date) {
        date.set(Calendar.HOUR_OF_DAY, 0);
        date.set(Calendar.MINUTE, 0);
        date.set(Calendar.SECOND, 0);
        date.set(Calendar.MILLISECOND, 0);
    }

    public static String formataDataEmString(Date data) {
        SimpleDateFormat out;
        try {
            out = new SimpleDateFormat("dd/MM/yyyy");
            return out.format(data);
        } catch (Exception e) {
            return "Erro ao formatar a Data";
        }
    }

    public static String formataDataHoraEmString(Date data) {
        SimpleDateFormat out;
        try {
            out = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
            return out.format(data);
        } catch (Exception e) {
            return "Erro ao formatar a data e hora";
        }
    }

    public static String formataHoraEmString(Date data) {
        SimpleDateFormat out;
        try {
            out = new SimpleDateFormat("HH:mm:ss");
            return out.format(data);
        } catch (Exception e) {
            return "Erro ao formatar a Hora";
        }
    }

    /**
     * Converte uma String para um objeto Date. Caso a String seja vazia ou nula,
     * retorna null - para facilitar em casos onde formulários podem ter campos
     * de datas vazios.
     * @param data String no formato dd/MM/yyyy a ser formatada
     * @return Date Objeto Date ou null caso receba uma String vazia ou nula
     * @throws Exception Caso a String esteja no formato errado
     */
    public static Date formataStringEmData(String data) {
        if (data == null || data.equals("")) {
            return null;
        }
        Date date = null;
        try {
            DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
            date = (java.util.Date) formatter.parse(data);
        } catch (Exception e) {
        }
        return date;
    }
}
